﻿using BE.Model;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;

namespace DAL
{
    public class DAL : IDAL
    {
        Jct_Dorms_DB db;

        public DAL()
        {
            Database.SetInitializer(new JctDormsInitializer());
            db = new Jct_Dorms_DB();
        }

        #region Cities
        public IEnumerable<BE.Model.City> GetAllCities()
        {
            return db.Cities.ToList();
        }

        public bool AddCity(BE.Model.City city)
        {
            try
            {
                db.Cities.Add(city);
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool RemoveCity(int id)
        {
            try
            {
                db.Cities.Remove(db.Cities.Find(id));
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool UpdateCity(City city)
        {
            try
            {
                db.Entry(city).State = System.Data.EntityState.Modified;
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

        #region Professions
        public IEnumerable<Profession> GetAllProfessions()
        {
            return db.Professions.ToList();
        }

        public bool AddProfession(Profession profession)
        {
            try
            {
                db.Professions.Add(profession);
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool RemoveProfession(int id)
        {
            try
            {
                db.Professions.Remove(db.Professions.Find(id));
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool UpdateProfession(Profession profession)
        {
            try
            {
                db.Entry(profession).State = System.Data.EntityState.Modified;
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

        #region Programs
        public IEnumerable<Program> GetAllPrograms()
        {
            return db.Programs.ToList();
        }

        public bool AddProgram(Program program)
        {
            try
            {
                db.Programs.Add(program);
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool RemoveProgram(int id)
        {
            try
            {
                db.Programs.Remove(db.Programs.Find(id));
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool UpdateProgram(Program program)
        {
            try
            {
                db.Entry(program).State = System.Data.EntityState.Modified;
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

        #region Dorms
        public IEnumerable<Dorm> GetAllDorms()
        {
            return db.Dorms.ToList();
        }

        public bool AddDorm(Dorm dorm)
        {
            if (dorm.NumberOfFloors <= 0)
                return false;

            try
            {
                db.Dorms.Add(dorm);
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }

        public bool RemoveDorm(int ID)
        {
            try
            {
                db.Dorms.Remove(db.Dorms.Find(ID));
                db.SaveChanges();

                return true;

            }
            catch (Exception ex)
            {

                return false;
            }
        }

        public bool UpdateDorm(Dorm dorm)
        {
            if (dorm.NumberOfFloors <= 0)
                return false;

            List<Room> roomsInDorm = db.Rooms.Where(r => r.DormID == dorm.ID).ToList();

            foreach (var r in roomsInDorm)
            {
                if (r.Floor > dorm.NumberOfFloors)
                    return false;
            }
            
            try
            {
                db.Entry(dorm).State = System.Data.EntityState.Modified;
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

        #region Rooms
        public IEnumerable<Room> GetAllRooms()
        {
            return db.Rooms.ToList();
        }

        public bool AddRoom(Room room)
        {
            Room toAdd = new Room();

            if (db.Charges.Find(room.ChargeID) == null || db.Dorms.Find(room.DormID) == null ||
                room.NumberOfBeds <= 0 || room.Floor <= 0 || room.Floor > db.Dorms.Find(room.DormID).NumberOfFloors)
                return false;

            try
            {
                toAdd.DormID = room.DormID;
                toAdd.Dorm = db.Dorms.Find(toAdd.DormID);
                toAdd.ChargeID = room.ChargeID;
                toAdd.Charge = db.Charges.Find(toAdd.ChargeID);
                toAdd.Number = room.Number;
                toAdd.Floor = room.Floor;
                toAdd.NumberOfBeds = room.NumberOfBeds;

                db.Rooms.Add(toAdd);
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }

        public bool RemoveRoom(int id)
        {
            try
            {
                db.Rooms.Remove(db.Rooms.Find(id));
                db.SaveChanges();
                return true;

            }
            catch (Exception ex)
            {

                return false;
            }
        }

        public bool UpdateRoom(Room room)
        {
            Room toUpdate = db.Rooms.Find(room.ID);

            if (room.Dorm == null || (db.Dorms.Find(room.DormID).ID != room.Dorm.ID) ||
                room.Charge == null || (db.Charges.Find(room.ChargeID).ID != room.Charge.ID) ||
                room.NumberOfBeds <= 0 || room.Floor <= 0 || room.Floor > db.Dorms.Find(room.DormID).NumberOfFloors )
                return false;

            try
            {
                toUpdate.DormID = room.DormID;
                toUpdate.Dorm = db.Dorms.Find(toUpdate.DormID);
                toUpdate.ChargeID = room.ChargeID;
                toUpdate.Charge = db.Charges.Find(toUpdate.ChargeID);
                toUpdate.Number = room.Number;
                toUpdate.Floor = room.Floor;
                toUpdate.NumberOfBeds = room.NumberOfBeds;

                db.Entry(toUpdate).State = System.Data.EntityState.Modified;
                db.SaveChanges();

                return true;

            }
            catch (Exception ex)
            {

                return false;
            }
        }
        #endregion

        #region Charges
        public IEnumerable<Charge> GetAllCharges()
        {
            return db.Charges.ToList();
        }

        public bool AddCharge(Charge charge)
        {
            if (charge.Amount <= 0)
                return false;

            try
            {
                db.Charges.Add(charge);
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }

        public bool RemoveCharge(int id)
        {
            try
            {
                db.Charges.Remove(db.Charges.Find(id));
                db.SaveChanges();
                return true;

            }
            catch (Exception ex)
            {

                return false;
            }
        }

        public bool UpdateCharge(Charge charge)
        {
            if (charge.Amount <= 0)
                return false;

            try
            {
                db.Entry(charge).State = System.Data.EntityState.Modified;
                db.SaveChanges();

                return true;

            }
            catch (Exception ex)
            {

                return false;
            }
        }
        #endregion

        #region Students
        public IEnumerable<Student> GetAllStudents()
        {
            return db.Students.ToList();
        }

        public bool AddStudent(Student student)
        {
            if (db.Cities.Find(student.CityID) == null ||
                db.Professions.Find(student.ProfessionID) == null ||
                db.Programs.Find(student.ProgramID) == null)
                return false;

            try
            {
                db.Students.Add(student);
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }

        public bool RemoveStudent(int id)
        {
            try
            {
                db.Students.Remove(db.Students.Find(id));
                db.SaveChanges();

                return true;

            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool UpdateStudent(Student student)
        {
            if (db.Cities.Find(student.CityID) == null ||
                db.Professions.Find(student.ProfessionID) == null ||
                db.Programs.Find(student.ProgramID) == null)
                return false;
            
            try
            {
                db.Entry(student).State = System.Data.EntityState.Modified;
                db.SaveChanges();

                return true;

            }
            catch (Exception ex)
            {

                return false;
            }
        }
        #endregion

        #region Placements
        public IEnumerable<Placement> GetAllPlacements()
        {
            return db.Placements.ToList();
        }

        public bool AddPlacement(Placement placement)
        {
            Placement toAdd = new Placement();

            if (db.Charges.Find(placement.ChargeID) == null ||
                db.Rooms.Find(placement.RoomID) == null ||
                db.Students.Find(placement.StudentID) == null )
                return false;

            try
            {
                toAdd.StudentID = placement.StudentID;
                toAdd.Student = db.Students.Find(toAdd.StudentID);
                toAdd.RoomID = placement.RoomID;
                toAdd.Room = db.Rooms.Find(toAdd.RoomID);
                toAdd.ChargeID = placement.ChargeID;
                toAdd.Charge = db.Charges.Find(toAdd.ChargeID);
                toAdd.ChargeStart = placement.ChargeStart; ;
                toAdd.ChargeEnd = placement.ChargeEnd;
                toAdd.Enterance = placement.Enterance;
                toAdd.Departure = placement.Departure;
                toAdd.Comments = placement.Comments;

                db.Placements.Add(toAdd);
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }

        public bool RemovePlacement(int id)
        {
            try
            {
                db.Placements.Remove(db.Placements.Find(id));
                db.SaveChanges();
                return true;

            }
            catch (Exception ex)
            {

                return false;
            }
        }

        public bool UpdatePlacement(Placement placement)
        {
            Placement toUpdate = db.Placements.Find(placement.ID);

            if (db.Charges.Find(placement.ChargeID) == null ||
                db.Rooms.Find(placement.RoomID) == null ||
                db.Students.Find(placement.StudentID) == null)
                return false;
            
            try
            {
                toUpdate.StudentID = placement.StudentID;
                toUpdate.Student = db.Students.Find(toUpdate.StudentID);
                toUpdate.RoomID = placement.RoomID;
                toUpdate.Room = db.Rooms.Find(toUpdate.RoomID);
                toUpdate.ChargeID = placement.ChargeID;
                toUpdate.Charge = db.Charges.Find(toUpdate.ChargeID);
                toUpdate.Comments = placement.Comments;

                db.Entry(toUpdate).State = System.Data.EntityState.Modified;
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }
        #endregion

        #region Users
        public IEnumerable<User> GetAllUsers()
        {
            return db.Users.ToList();
        }

        public bool AddUser(User user)
        {
            try
            {
                db.Users.Add(user);
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool RemoveUser(int id)
        {
            try
            {
                db.Users.Remove(db.Users.Find(id));
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool UpdateUser(User user)
        {
            try
            {
                db.Entry(user).State = System.Data.EntityState.Modified;
                db.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public User GetUserByID(int id)
        {
            return db.Users.Find(id);
        }

        public User GetUserByEmail(string email)
        {
            return db.Users.Where(u => u.Email.Equals(email, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
        }
        #endregion

    }
}
